home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xearth-0.92 / sunpos.c < prev    next >
C/C++ Source or Header  |  1995-06-25  |  7KB  |  251 lines

  1. /*
  2.  * sunpos.c
  3.  * kirk johnson
  4.  * july 1993
  5.  *
  6.  * code for calculating the position on the earth's surface for which
  7.  * the sun is directly overhead (adapted from _practical astronomy
  8.  * with your calculator, third edition_, peter duffett-smith,
  9.  * cambridge university press, 1988.)
  10.  *
  11.  * RCS $Id: sunpos.c,v 1.2 1994/05/20 01:37:40 tuna Exp $
  12.  *
  13.  * Copyright (C) 1989, 1990, 1993, 1994 Kirk Lauritz Johnson
  14.  *
  15.  * Parts of the source code (as marked) are:
  16.  *   Copyright (C) 1989, 1990, 1991 by Jim Frost
  17.  *   Copyright (C) 1992 by Jamie Zawinski <jwz@lucid.com>
  18.  *
  19.  * Permission to use, copy, modify, distribute, and sell this
  20.  * software and its documentation for any purpose is hereby granted
  21.  * without fee, provided that the above copyright notice appear in
  22.  * all copies and that both that copyright notice and this
  23.  * permission notice appear in supporting documentation. The author
  24.  * makes no representations about the suitability of this software
  25.  * for any purpose. It is provided "as is" without express or
  26.  * implied warranty.
  27.  *
  28.  * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  29.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  30.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT
  31.  * OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  32.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  33.  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  34.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  35.  */
  36.  
  37. #include "xearth.h"
  38. #include "kljcpyrt.h"
  39.  
  40. #define TWOPI (2*M_PI)
  41.  
  42. /*
  43.  * the epoch upon which these astronomical calculations are based is
  44.  * 1990 january 0.0, 631065600 seconds since the beginning of the
  45.  * "unix epoch" (00:00:00 GMT, Jan. 1, 1970)
  46.  *
  47.  * given a number of seconds since the start of the unix epoch,
  48.  * DaysSinceEpoch() computes the number of days since the start of the
  49.  * astronomical epoch (1990 january 0.0)
  50.  */
  51.  
  52. #define EpochStart           (631065600)
  53. #define DaysSinceEpoch(secs) (((secs)-EpochStart)*(1.0/(24*3600)))
  54.  
  55. /*
  56.  * assuming the apparent orbit of the sun about the earth is circular,
  57.  * the rate at which the orbit progresses is given by RadsPerDay --
  58.  * TWOPI radians per orbit divided by 365.242191 days per year:
  59.  */
  60.  
  61. #define RadsPerDay (TWOPI/365.242191)
  62.  
  63. /*
  64.  * details of sun's apparent orbit at epoch 1990.0 (after
  65.  * duffett-smith, table 6, section 46)
  66.  *
  67.  * Epsilon_g    (ecliptic longitude at epoch 1990.0) 279.403303 degrees
  68.  * OmegaBar_g   (ecliptic longitude of perigee)      282.768422 degrees
  69.  * Eccentricity (eccentricity of orbit)                0.016713
  70.  */
  71.  
  72. #define Epsilon_g    (279.403303*(TWOPI/360))
  73. #define OmegaBar_g   (282.768422*(TWOPI/360))
  74. #define Eccentricity (0.016713)
  75.  
  76. /*
  77.  * MeanObliquity gives the mean obliquity of the earth's axis at epoch
  78.  * 1990.0 (computed as 23.440592 degrees according to the method given
  79.  * in duffett-smith, section 27)
  80.  */
  81. #define MeanObliquity (23.440592*(TWOPI/360))
  82.  
  83.  
  84. /*
  85.  * solve Kepler's equation via Newton's method
  86.  * (after duffett-smith, section 47)
  87.  */
  88. static double solve_keplers_equation(M)
  89.      double M;
  90. {
  91.   double E;
  92.   double delta;
  93.  
  94.   E = M;
  95.   while (1)
  96.   {
  97.     delta = E - Eccentricity*sin(E) - M;
  98.     if (fabs(delta) <= 1e-10) break;
  99.     E -= delta / (1 - Eccentricity*cos(E));
  100.   }
  101.  
  102.   return E;
  103. }
  104.  
  105.  
  106. /*
  107.  * compute ecliptic longitude of sun (in radians)
  108.  * (after duffett-smith, section 47)
  109.  */
  110. static double sun_ecliptic_longitude(ssue)
  111.      time_t ssue;               /* seconds since unix epoch */
  112. {
  113.   double D, N;
  114.   double M_sun, E;
  115.   double v;
  116.  
  117.   D = DaysSinceEpoch(ssue);
  118.  
  119.   N = RadsPerDay * D;
  120.   N = fmod(N, TWOPI);
  121.   if (N < 0) N += TWOPI;
  122.  
  123.   M_sun = N + Epsilon_g - OmegaBar_g;
  124.   if (M_sun < 0) M_sun += TWOPI;
  125.  
  126.   E = solve_keplers_equation(M_sun);
  127.   v = 2 * atan(sqrt((1+Eccentricity)/(1-Eccentricity)) * tan(E/2));
  128.  
  129.   return (v + OmegaBar_g);
  130. }
  131.  
  132.  
  133. /*
  134.  * convert from ecliptic to equatorial coordinates
  135.  * (after duffett-smith, section 27)
  136.  */
  137. static void ecliptic_to_equatorial(lambda, beta, alpha, delta)
  138.      double  lambda;            /* ecliptic longitude       */
  139.      double  beta;              /* ecliptic latitude        */
  140.      double *alpha;             /* (return) right ascension */
  141.      double *delta;             /* (return) declination     */
  142. {
  143.   double sin_e, cos_e;
  144.  
  145.   sin_e = sin(MeanObliquity);
  146.   cos_e = cos(MeanObliquity);
  147.  
  148.   *alpha = atan2(sin(lambda)*cos_e - tan(beta)*sin_e, cos(lambda));
  149.   *delta = asin(sin(beta)*cos_e + cos(beta)*sin_e*sin(lambda));
  150. }
  151.  
  152.  
  153. /*
  154.  * computing julian dates (assuming gregorian calendar, thus this is
  155.  * only valid for dates of 1582 oct 15 or later)
  156.  * (after duffett-smith, section 4)
  157.  */
  158. static double julian_date(y, m, d)
  159.      int y;                     /* year (e.g. 19xx)          */
  160.      int m;                     /* month (jan=1, feb=2, ...) */
  161.      int d;                     /* day of month              */
  162. {
  163.   int    A, B, C, D;
  164.   double JD;
  165.  
  166.   /* lazy test to ensure gregorian calendar */
  167.   assert(y >= 1583);
  168.  
  169.   if ((m == 1) || (m == 2))
  170.   {
  171.     y -= 1;
  172.     m += 12;
  173.   }
  174.  
  175.   A = y / 100;
  176.   B = 2 - A + (A / 4);
  177.   C = 365.25 * y;
  178.   D = 30.6001 * (m + 1);
  179.  
  180.   JD = B + C + D + d + 1720994.5;
  181.  
  182.   return JD;
  183. }
  184.  
  185.  
  186. /*
  187.  * compute greenwich mean sidereal time (GST) corresponding to a given
  188.  * number of seconds since the unix epoch
  189.  * (after duffett-smith, section 12)
  190.  */
  191. static double GST(ssue)
  192.      time_t ssue;               /* seconds since unix epoch */
  193. {
  194.   double     JD;
  195.   double     T, T0;
  196.   double     UT;
  197.   struct tm *tm;
  198.  
  199.   tm = gmtime(&ssue);
  200.  
  201.   JD = julian_date(tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);
  202.   T  = (JD - 2451545) / 36525;
  203.  
  204.   T0 = ((T + 2.5862e-5) * T + 2400.051336) * T + 6.697374558;
  205.  
  206.   T0 = fmod(T0, 24.0);
  207.   if (T0 < 0) T0 += 24;
  208.  
  209.   UT = tm->tm_hour + (tm->tm_min + tm->tm_sec / 60.0) / 60.0;
  210.  
  211.   T0 += UT * 1.002737909;
  212.   T0 = fmod(T0, 24.0);
  213.   if (T0 < 0) T0 += 24;
  214.  
  215.   return T0;
  216. }
  217.  
  218.  
  219. /*
  220.  * given a particular time (expressed in seconds since the unix
  221.  * epoch), compute position on the earth (lat, lon) such that sun is
  222.  * directly overhead.
  223.  */
  224. void sun_position(ssue, lat, lon)
  225.      time_t  ssue;              /* seconds since unix epoch */
  226.      double *lat;               /* (return) latitude        */
  227.      double *lon;               /* (return) longitude       */
  228. {
  229.   double lambda;
  230.   double alpha, delta;
  231.   double tmp;
  232.  
  233.   lambda = sun_ecliptic_longitude(ssue);
  234.   ecliptic_to_equatorial(lambda, 0.0, &alpha, &delta);
  235.  
  236.   tmp = alpha - (TWOPI/24)*GST(ssue);
  237.   if (tmp < -M_PI)
  238.   {
  239.     do tmp += TWOPI;
  240.     while (tmp < -M_PI);
  241.   }
  242.   else if (tmp > M_PI)
  243.   {
  244.     do tmp -= TWOPI;
  245.     while (tmp < -M_PI);
  246.   }
  247.  
  248.   *lon = tmp * (360/TWOPI);
  249.   *lat = delta * (360/TWOPI);
  250. }
  251.